15.3 Die Internas einer Windowsanwendung  
Nachdem wir nun die erste Windowsanwendung entwickelt haben, sollten wir uns im Projektmappen-Explorer alle Projektdateien des Beispiels anzeigen lassen. Klicken dazu auf die entsprechende Symbolleistenschaltfläche. Nun wird auch eine der Quellcodedatei Form1.vb untergeordnete Datei angezeigt, die Form1.Designer.vb heißt und den folgenden Inhalt hat:
| <Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
|
| Partial Class Form1
|
| Inherits System.Windows.Forms.Form
|
| 'Das Formular überschreibt den Löschvorgang, um die
|
| 'Komponentenliste zu bereinigen.
|
| <System.Diagnostics.DebuggerNonUserCode()> _
|
| Protected Overrides Sub Dispose(ByVal disposing As Boolean)
|
| If disposing AndAlso components IsNot Nothing Then
|
| components.Dispose()
|
| End If
|
| MyBase.Dispose(disposing)
|
| End Sub
|
| 'Wird vom Windows Form-Designer benötigt.
|
| Private components As System.ComponentModel.IContainer
|
| 'Hinweis: Die folgende Prozedur ist für den Windows
|
| 'Form-Designer erforderlich.
|
| 'Das Bearbeiten ist mit dem Windows Form-Designer
|
| 'möglich.
|
| 'Das Bearbeiten mit dem Code-Editor ist nicht möglich.
|
| <System.Diagnostics.DebuggerStepThrough()> _
|
| Private Sub InitializeComponent()
|
| Me.btnKopieren = New System.Windows.Forms.Button
|
| Me.btnBeenden = New System.Windows.Forms.Button
|
| Me.txtOriginal = New System.Windows.Forms.TextBox
|
| Me.txtKopie = New System.Windows.Forms.TextBox
|
| Me.SuspendLayout()
|
| '
|
| 'btnKopieren
|
| '
|
| Me.btnKopieren.Location = New System.Drawing.Point(241, 13)
|
| Me.btnKopieren.Name = "btnKopieren"
|
| Me.btnKopieren.Size = New System.Drawing.Size(101, 23)
|
| Me.btnKopieren.TabIndex = 0
|
| Me.btnKopieren.Text = "Kopieren"
|
| Me.btnKopieren.UseVisualStyleBackColor = True
|
| '
|
| 'btnBeenden
|
| '
|
| Me.btnBeenden.Location = New System.Drawing.Point(242, 51)
|
| Me.btnBeenden.Name = "btnBeenden"
|
| Me.btnBeenden.Size = New System.Drawing.Size(101, 23)
|
| Me.btnBeenden.TabIndex = 1
|
| Me.btnBeenden.Text = "Beenden"
|
| Me.btnBeenden.UseVisualStyleBackColor = True
|
| '
|
| 'txtOriginal
|
| '
|
| Me.txtOriginal.Location = New System.Drawing.Point(13, 15)
|
| Me.txtOriginal.Name = "txtOriginal"
|
| Me.txtOriginal.Size = New System.Drawing.Size(165, 20)
|
| Me.txtOriginal.TabIndex = 2
|
| Me.txtOriginal.Text = "Testtext"
|
| '
|
| 'txtKopie
|
| '
|
| Me.txtKopie.Location = New System.Drawing.Point(13, 54)
|
| Me.txtKopie.Name = "txtKopie"
|
| Me.txtKopie.Size = New System.Drawing.Size(165, 20)
|
| Me.txtKopie.TabIndex = 3
|
| '
|
| 'Form1
|
| '
|
| Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
|
| Me.AutoScaleMode = _
|
| System.Windows.Forms.AutoScaleMode.Font
|
| Me.ClientSize = New System.Drawing.Size(355, 126)
|
| Me.Controls.Add(Me.txtKopie)
|
| Me.Controls.Add(Me.txtOriginal)
|
| Me.Controls.Add(Me.btnBeenden)
|
| Me.Controls.Add(Me.btnKopieren)
|
| Me.Name = "Form1"
|
| Me.Text = "Meine erste WinAnwendung"
|
| Me.ResumeLayout(False)
|
| Me.PerformLayout()
|
| End Sub
|
| Friend WithEvents btnKopieren As System.Windows.Forms.Button
|
| Friend WithEvents btnBeenden As System.Windows.Forms.Button
|
| Friend WithEvents txtOriginal As System.Windows.Forms.TextBox
|
| Friend WithEvents txtKopie As System.Windows.Forms.TextBox
|
| End Class
|
Mit dem .NET Framework 2.0 wurden partielle Klassen eingeführt, um den Quellcode auf zwei oder mehr Quellcodedateien aufzuteilen. Bei der Implementierung einer Form-Klasse wird ebenfalls eine partielle Klassedefinition bereitgestellt. In unserer ersten Windowsanwendung ist der Code auf die Dateien Form1.vb und Form1.Designer.vb aufgeteilt.
Entwickeln Sie eine Windowsanwendung, wird vom Visual Studio 2005 sehr umfangreicher Code automatisch generiert. Dieser ist in der Methode InitializeComponent der Datei Form1.Designer.vb zu finden, die ebenfalls vom automatisch vom Visual Sudio 2005 bereitgestellt wird. In erster Linie werden in dieser Methode Eigenschaftseinstellungen der Komponenten beschrieben, die von der Standardvorgabe des jeweiligen Typs abweichen, also objektspezifisch sind und von Ihnen im Eigenschaftsfenster vorgenommen worden sind.
Beachten Sie auch bitte unbedingt den XML-Kommentar zu InitializeComponent. Aus eigener Erfahrung kann ich Ihnen nahe legen, diesen zu beherzigen und wirklich keine Änderungen am Code in InitializeComponent vornehmen. In einigen Fällen, in denen ich aus einer gewissen Sturheit heraus diesen Hinweis ignoriert habe, musste ich meine Ignoranz mit dem Verlust sämtlicher Steuerelemente in einer Form bezahlen.
Neben der Initialisierungsmethode werden auf Klassenebene auch alle Steuerelemente standardmäßig Friend und WithEvents deklariert, sind also für die Verarbeitung ausgelöster Ereignisse vorbereitet.
Der Vorteil partieller Klassen wird spätestens jetzt auf zweierlei Weise deutlich:
|
Der benutzerdefinierte Code ist von dem Code, den die Entwicklungsumgebung generiert, getrennt. Dadurch wird der Entwickler nicht so schnell der Verlockung nachgeben, eventuell doch Änderungen in InitializeComponent durchzuführen. |
|
Der wesentliche Teil des Programmcodes, nämlich der benutzerdefinierte, wird überschaubarer, was insbesondere einem Programmieranfänger den Einstieg erleichtert. |
15.3.1 Projekteinstellungen  
Mehrere allgemeine Einstellungen lassen sich im Projekteigenschaftsfenster vornehmen, dass Sie durch Doppelklick des Knotens My Project im Projektmappen-Explorer öffnen (siehe Abbildung 15.5).
 Hier klicken, um das Bild zu Vergrößern
Abbildung 15.5 Projekteinstellungen
Unter Startformular geben Sie an, welche Form beim Programmstart geöffnet wird. Deselektieren Sie Anwendungsframework aktivieren, können Sie auch eine Main-Methode angeben, die Sie dann selbst codieren müssen. Wie das gemacht wird, zeige ich Ihnen später. Die Vorgabe ist, dass das erste Fenster einer Windowsanwendung als Startfenster festgelegt ist.
15.3.2 Das Anwendungsframework  
Eine Neuerung von Visual Basic 2005 ist das Anwendungsframework, das standardmäßig aktiviert ist. Es unterstützt Sie in einigen Belangen und erleichtert so die Programmierarbeit. Die folgenden Einstellungen können zur Konfiguration der Windowsanwendung eingestellt werden, wenn das Kontrollkästchen Anwendungsframework aktivieren aktiviert ist:
Visuelle XP-Stile aktivieren: Hiermit wird festgelegt, dass das Programm das Layout von Windows XP benutzen soll. Visuelle XP-Stile lassen beispielsweise gerundete Ecken und dynamische Farben zu.
Einzelinstanzanwendung erstellen: Diese Einstellung bewirkt, dass die Anwendung nicht mehrfach gestartet werden kann. Per Vorgabe ist diese Option deaktiviert.
Eigene Einstellungen beim Herunterfahren speichern: Mit Aktivierung dieser Option wird sichergestellt, dass die My.Settings-Programmeinstellungen beim Beenden der Anwendung automatisch gespeichert werden. Deaktivieren Sie diese Option, müssen Sie durch Aufruf von My.Settings.Save() selbst das Speichern in die Hand nehmen. Im Kapitel 27 erfahren Sie mehr über My.Settings.
Authentifizierungsmodus: Die Standardeinstellung Windows bewirkt, dass das Programm die Anmeldedaten des aktuellen Benutzers übernimmt. Wenn Sie die Vorgabe nicht akzeptieren können, wählen sie die Option Anwendungsdefiniert aus, sind dann aber auch selbst für die Authentifizierung verantwortlich und müssen entsprechenden Code schreiben.
Modus für das Herunterfahren: Hier stellen Sie ein, wann eine laufende Windowsanwendung geschlossen wird. Die Vorgabe lautet Beim Schließen des Startformulars. Mit der zweiten zur Verfügung stehenden Option können Sie die Anwendung beenden, wenn das letzte Fenster geschlossen wird.
Begrüßungsbildschirm: Hier stellen Sie ein, ob eine Form als Begrüßungsfenster (Splash-Fenster) angezeigt werden soll und welches.
15.3.3 Die Klasse »MyApplication«  
Die Einstellungen, die Sie unter My Project/Anwendung vornehmen, werden in einem Objekt abgelegt. Die zugrunde liegende Klasse MyApplication ist, auch wenn es nicht offensichtlich ist, von der Klasse WindowsFormsApplicationBase abgeleitet, die sich im Namespace Microsoft.VisualBasic.ApplicationServices befindet. Den Code der Klasse MyApplication finden Sie in der Datei Application.Designer.vb und könnte beispielsweise wie folgt aussehen:
| Namespace My
|
| Partial Friend Class MyApplication
|
| <Global.System.Diagnostics.DebuggerStepThroughAttribute()> _
|
| Public Sub New()
|
| MyBase.New(Global.Microsoft.VisualBasic.
|
| ApplicationServices.AuthenticationMode.Windows)
|
| Me.IsSingleInstance = false
|
| Me.EnableVisualStyles = true
|
| Me.SaveMySettingsOnExit = true
|
| Me.ShutDownStyle = _
|
| Global.Microsoft.VisualBasic.ApplicationServices.
|
| ShutdownMode.AfterMainFormCloses
|
| End Sub
|
| <Global.System.Diagnostics.DebuggerStepThroughAttribute()> _
|
| Protected Overrides Sub OnCreateMainForm()
|
| Me.MainForm = Global.WindowsApplication1.Form1
|
| End Sub
|
| End Class
|
| End Namespace
|
Sie können das Objekt vom Typ My.MyApplication im eigenen Code unter dem Namen My.Application ansprechen. Allerdings sollten Sie dieses Application-Objekt nicht mit dem verwechseln, das sich im Namespace System.Windows.Forms befindet. Letztgenanntes stellt mehrere statische Eigenschaften und Methoden bereit, mit denen Sie das laufende Programm beeinflussen können oder dessen Eigenschaften abrufen können.
15.3.4 Die Ereignisse des »MyApplication«-Objekts  
Das MyApplication-Objekt kennt mehrere Ereignisse.
Tabelle 15.2 Die Ereignisse des »MyApplication«-Objekts
| Ereignis
|
Beschreibung
|
| NetworkAvailabilityChanged
|
Wird ausgelöst, wenn eine Netzwerkverbindung hergestellt oder unterbrochen wird.
|
| ShutDown
|
Wird bei einem normalen Beenden der Anwendung ausgelöst. Das Ereignis wird nicht ausgelöst, wenn beispielsweise eine unbehandelte Ausnahme auftritt.
|
| Startup
|
Wird ausgelöst, wenn das Programm gestartet wird. Das Ereignis tritt noch vor dem Erstellen des Startformulars auf.
|
| StartUpNextInstance
|
Dieses Ereignis tritt nur dann auf, wenn eine Anwendung nicht mehrfach gestartet werden kann und versucht wird, eine weitere Instanz zu starten.
|
| UnhandledException
|
Tritt auf, wenn ein nicht behandelter Fehler zur Laufzeit ausgelöst wird.
|
Codieren können Sie die Ereignisse auf zwei verschiedene Weisen:
Klicken Sie im Projekteigenschaftsfenster auf die Schaltfläche Anwendungsereignisse anzeigen. Daraufhin erzeugt das Visual Studio 2005 die Datei ApplicationEvents.vb. Dort können Sie die Ereignisse programmieren.
Stellen Sie im Codeeditor der Datei Application.Designer.vb im linken Listenfeld MyApplication-Ereignisse ein und wählen Sie aus der rechten Liste das gewünschte Ereignis aus. Der entsprechende Ereignishandler wird im Code automatisch erzeugt (siehe Abbildung 15.6).
Ein Wort sollte noch zu dem Ereignis UnhandledException gesagt werden. Tritt zur Laufzeit ein Fehler auf, der im Programmcode nicht behandelt wird, gilt generell, dass die Anwendung unplanmäßig beendet wird. Mit dem Ereignis UnhandledException haben Sie aber die Möglichkeit, eine zentrale »Anlaufstelle« zur Fehlerabsicherung zu schaffen. Tritt in irgendeiner der Methoden Ihres Programms ein Fehler auf, kann er im Ereignishandler von UnhandledException aufgefangen werden. Dem Beenden der Anwendung wirken Sie entgegen, wenn Sie im Ereignishandler die Eigenschaft ExitApplication des zweiten Parameters vom Typ UnhandledExceptionEventArgs auf False einstellen, also:
| Private Sub MyApplication_UnhandledException(ByVal sender As Object, _
|
| ByVal e As UnhandledExceptionEventArgs) _
|
| Handles Me.UnhandledException
|
| e.ExitApplication = False
|
| End Sub
|
 Hier klicken, um das Bild zu Vergrößern
Abbildung 15.6 Ereignisse des »MyApplication«-Objekts programmieren
Die Startroutine »Main« selbst implementieren
Jede eigenstartfähige Anwendung benötigt eine Methode Main, die als Einstiegspunkt in die Anwendung dient. Das gilt für Konsolenanwendungen und gleichermaßen auch für Windowsprogramme. Eine Main-Methode werden Sie aber im bisherigen Code nicht entdecken, sie ist regelrecht versteckt und agiert nur im Hintergrund.
Sie können die Startmethode auch selbst implementieren. Dazu ist es zunächst notwendig, das Anwendungsframework zu deaktivieren. Fügen Sie anschließend eine neue Klasse oder ein Modul hinzu und codieren Sie darin Main beispielsweise wie folgt:
| Public Class Start
|
| Public Shared Sub Main()
|
| Application.EnableVisualStyles()
|
| Application.Run(New Form1())
|
| End Sub
|
| End Class
|
Ein grundlegender Unterschied zwischen einer Konsolen- und einer Windowsanwendung ist die sogenannte Nachrichtenschleife. Als Nachricht ist ein Ereignis zu verstehen. Windowsprogramme reagieren auf Ereignisse und eine Nachrichtenschleife ist sensibilisiert, ununterbrochen auf eingehende Ereignisse zu lauern. Ob es sich um Ereignisse der Maus, der Tastatur oder um Ereignisse von Peripheriegeräten wie beispielsweise dem Drucker handelt, spielt keine Rolle.
Beim Starten einer Windowsanwendung wird nicht automatisch eine Nachrichtenschleife erstellt; das muss ausdrücklich im Programmcode erfolgen. Dazu dient die statische Methode Run der Klasse Application.
| Application.Run(New Form1())
|
Als Argument wird Run eine neue Instanz der Klasse Form1 übergeben. Dabei handelt es sich um das Anwendungsfenster, das in den beiden Dateien Form1.vb und Form1.Designer.vb definiert ist. Beim Aufruf von Run passieren mehrere Dinge:
|
Es wird eine Nachrichtenschleife gestartet. |
|
Es wird ein Objekt vom Typ Form1 erzeugt. |
|
Das Form-Objekt wird angezeigt. |
Jeder Start einer Anwendung hat zur Folge, dass ein neuer Prozess eröffnet wird der einen Thread hat, in dem sich die Vorgänge der Anwendung abspielen (zumindest so lange Sie keinen zusätzlichen Thread erstellen). Eine Nachrichtenschleife ist immer an einen bestimmten Thread gebunden. Durch den Aufruf von Run mit Übergabe einer Form1-Instanz wird die Nachrichtenschleife an den Primärthread der Anwendung und darüber hinaus auch an die Form gebunden. Schließen Sie das Form-Objekt, wird auch die Anwendung beendet. Es handelt sich hierbei gewissermaßen um das Hauptfenster der Anwendung.
Werden aus dem Hauptfenster heraus weitere Fenster geöffnet und das Hauptfenster anschließend geschlossen, wird die Laufzeit der Anwendung beendet. Das hat zur Folge, dass automatisch alle anderen noch geöffneten Fenster geschlossen werden.
Application.Run ist überladen. Sie können auch die parameterlose Variante einsetzen und haben damit erreicht, dass die Lebensdauer der Nachrichtenschleife nicht mehr an die Existenz der Startform gebunden ist.
| Dim frm As New Form1()
|
| frm.Show()
|
| Application.Run()
|
Jetzt verhält sich die Anwendung ganz anders, denn mit dem Schließen der Form wird die Anwendung nicht beendet. Sie sehen die Form zwar nicht mehr, aber die Nachrichtenschleife lebt weiter und wartet auf Ereignisse, die nicht mehr kommen können.
Durch den Aufruf der Methode Application.EnableVisualStyles geben Sie an, den Windows XP-Stil wenn möglich anzuwenden. Dieser Methodenaufruf findet seine Entsprechung auch im Anwendungsframework, wie Sie weiter oben schon gesehen haben.
|